package per.turtle.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import per.turtle.common.core.constant.CacheConstants;
import per.turtle.common.redis.service.RedisService;
import per.turtle.system.entity.SysDictData;
import per.turtle.system.entity.SysDictType;
import per.turtle.system.mapper.SysDictDataMapper;
import per.turtle.system.mapper.SysDictTypeMapper;
import per.turtle.system.service.ISysDictDataService;

import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.List;

/**
 * 字典 服务层实现
 *
 * @author turtle
 */
@RequiredArgsConstructor
@Service
public class SysDictDataServiceImpl extends ServiceImpl<SysDictDataMapper, SysDictData> implements ISysDictDataService {

    private final RedisService redisService;

    private final SysDictTypeMapper dictTypeMapper;

    @Override
    public void deleteDictDataById(Long dictCode) {
        SysDictData data = baseMapper.selectById(dictCode);
        int row = baseMapper.deleteById(dictCode);
        if (row > 0) {
            redisService.setCacheObject(data.getDictType(), this.selectDictDataByType(data.getDictType()));
        }
    }

    @CachePut(value = CacheConstants.SYS_DICT_KEY, key = "#data.dictType", unless = "#result == null")
    @Override
    public List<SysDictData> insertDictData(SysDictData data) {
        int row = baseMapper.insert(data);
        if (row > 0) {
            return this.selectDictDataByType(data.getDictType());
        }
        return null;
    }

    @Override
    public void resetDictCache() {
        clearDictCache();
        loadingDictCache();
    }

    @Cacheable(value = CacheConstants.SYS_DICT_KEY, key = "#dictType")
    @Override
    public List<SysDictData> selectDictDataByType(String dictType) {
        QueryWrapper<SysDictData> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(StrUtil.isNotBlank(dictType), SysDictData::getDictType, dictType);
        return baseMapper.selectList(wrapper);
    }

    @Override
    public List<SysDictData> selectDictDataList(SysDictData dictData) {
        QueryWrapper<SysDictData> wrapper = new QueryWrapper<>(dictData);
        wrapper.getEntity().setDictLabel(null);
        wrapper.lambda().like(StrUtil.isNotBlank(dictData.getDictLabel()), SysDictData::getDictLabel, dictData.getDictLabel());
        return baseMapper.selectList(wrapper);
    }

    @Override
    public String selectDictLabel(String dictType, String dictValue) {
        if (StrUtil.isNotBlank(dictType) && StrUtil.isNotBlank(dictValue)) {
            QueryWrapper<SysDictData> wrapper = new QueryWrapper<>();
            wrapper.lambda().select(SysDictData::getDictLabel);
            wrapper.lambda().eq(SysDictData::getDictType, dictType).eq(SysDictData::getDictValue, dictValue);
            return baseMapper.selectOne(wrapper).getDictLabel();
        }
        return null;
    }

    @CachePut(value = CacheConstants.SYS_DICT_KEY, key = "#data.dictType", unless = "#result == null")
    @Override
    public List<SysDictData> updateDictData(SysDictData data) {
        int row = baseMapper.updateById(data);
        if (row > 0) {
            return this.selectDictDataByType(data.getDictType());
        }
        return null;
    }

    @PostConstruct
    public void init() {
        loadingDictCache();
    }

    private void clearDictCache() {
        Collection<String> keys = redisService.keys(CacheConstants.SYS_DICT_KEY + "*");
        redisService.deleteObject(keys);
    }

    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configKey) {
        return CacheConstants.SYS_DICT_KEY + configKey;
    }

    private void loadingDictCache() {
        List<SysDictType> dictTypeList = dictTypeMapper.selectList(new QueryWrapper<>());
        for (SysDictType dictType : dictTypeList) {
            List<SysDictData> dictDatas = this.selectDictDataByType(dictType.getDictType());
            redisService.setCacheObject(this.getCacheKey(dictType.getDictType()), dictDatas);
        }
    }

}
